package com.fx.zmlzml.algorithm.util;

import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.special.Erf;

/**
 * 数学工具类
 */
public class MathUtils {

    /**
     * 计算标准高斯函数（均值为0，标准差为1）的值
     *
     * @param x 输入值
     * @return 高斯函数值
     */
    public static double gaussian(double x) {
        return gaussian(x, 0, 1);
    }

    /**
     * 计算高斯函数的值
     *
     * @param x 输入值
     * @param mean 均值
     * @param stdDev 标准差
     * @return 高斯函数值
     * @throws IllegalArgumentException 当标准差小于等于0时抛出异常
     */
    public static double gaussian(double x, double mean, double stdDev) {
        if (stdDev <= 0) {
            throw new IllegalArgumentException("标准差必须大于0");
        }

        NormalDistribution normalDist = new NormalDistribution(mean, stdDev);
        return normalDist.density(x); // 使用Apache Commons Math计算概率密度函数 [[4]]
    }

    /**
     * 计算累积分布函数(CDF)值
     *
     * @param x 输入值
     * @param mean 均值
     * @param stdDev 标准差
     * @return CDF值
     */
    public static double gaussianCDF(double x, double mean, double stdDev) {
        if (stdDev <= 0) {
            throw new IllegalArgumentException("标准差必须大于0");
        }

        NormalDistribution normalDist = new NormalDistribution(mean, stdDev);
        return normalDist.cumulativeProbability(x); // 计算累积分布函数 [[8]]
    }

    /**
     * 误差函数（erf）
     *
     * @param x 输入值
     * @return erf(x)值
     */
    public static double erf(double x) {
        return Erf.erf(x); // 使用Apache Commons Math提供的精确erf实现
    }

    /**
     * 生成高斯核（用于图像处理）
     *
     * @param radius 核半径
     * @param sigma 标准差
     * @return 归一化的高斯核
     */
    public static double[] createGaussianKernel(int radius, double sigma) {
        int size = radius * 2 + 1;
        double[] kernel = new double[size];
        double sum = 0.0;

        // 使用NormalDistribution计算核值
        NormalDistribution normalDist = new NormalDistribution(0, sigma);
        for (int i = 0; i < size; i++) {
            double x = i - radius;
            kernel[i] = normalDist.density(x);
            sum += kernel[i];
        }

        // 归一化
        for (int i = 0; i < size; i++) {
            kernel[i] /= sum;
        }

        return kernel;
    }

}
